package com.pokermind.common.util;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 牌面编码转换工具
 * 
 * V4.4: 业务侧数字编码与标准牌面格式的双向转换
 * 
 * 业务侧编码规则（0-51）：
 * - 0-12:   方片A-K (Diamonds)
 * - 13-25:  梅花A-K (Clubs)
 * - 26-38:  红桃A-K (Hearts)
 * - 39-51:  黑桃A-K (Spades)
 * 
 * 标准牌面格式：
 * - 点数：A, 2-9, T(10), J, Q, K
 * - 花色：d(方块), c(梅花), h(红桃), s(黑桃)
 * - 示例：Ah(红桃A), Kd(方块K), 7c(梅花7)
 * 
 * @author PokerMind Team
 * @version V4.4
 */
public class CardCodec {
    
    // 点数映射：数字索引 → 标准点数符号
    private static final char[] RANKS = {
        'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K'
    };
    
    // 花色映射：业务侧顺序
    private static final char[] SUITS = {
        'd',  // 0-12:   方片 (Diamonds)
        'c',  // 13-25:  梅花 (Clubs)
        'h',  // 26-38:  红桃 (Hearts)
        's'   // 39-51:  黑桃 (Spades)
    };
    
    // 花色中文名称
    private static final String[] SUIT_NAMES_ZH = {
        "方块", "梅花", "红桃", "黑桃"
    };
    
    // 花色英文名称
    private static final String[] SUIT_NAMES_EN = {
        "Diamonds", "Clubs", "Hearts", "Spades"
    };
    
    // 标准格式验证正则
    private static final Pattern CARD_PATTERN = Pattern.compile("^[A2-9TJQK][dhcs]$");
    
    // 反向映射缓存：标准格式 → 数字编码
    private static final Map<String, Integer> CARD_TO_CODE = new HashMap<>(52);
    
    static {
        // 初始化反向映射
        for (int code = 0; code < 52; code++) {
            String card = encodeToStandard(code);
            CARD_TO_CODE.put(card, code);
        }
    }
    
    /**
     * 将业务侧数字编码转换为标准牌面格式
     * 
     * @param code 业务侧编码 (0-51)
     * @return 标准格式字符串，如 "Ah", "Kd"
     * @throws IllegalArgumentException 如果编码超出范围
     * 
     * 示例：
     * - encodeToStandard(0)  → "Ad" (方片A)
     * - encodeToStandard(12) → "Kd" (方片K)
     * - encodeToStandard(26) → "Ah" (红桃A)
     * - encodeToStandard(51) → "Ks" (黑桃K)
     */
    public static String encodeToStandard(int code) {
        if (code < 0 || code > 51) {
            throw new IllegalArgumentException("Invalid card code: " + code + ". Must be 0-51.");
        }
        
        int suitIndex = code / 13;    // 花色索引 (0-3)
        int rankIndex = code % 13;    // 点数索引 (0-12)
        
        char rank = RANKS[rankIndex];
        char suit = SUITS[suitIndex];
        
        return String.valueOf(rank) + suit;
    }
    
    /**
     * 将标准牌面格式转换为业务侧数字编码
     * 
     * @param card 标准格式字符串，如 "Ah", "Kd"
     * @return 业务侧编码 (0-51)
     * @throws IllegalArgumentException 如果格式不正确
     * 
     * 示例：
     * - decodeFromStandard("Ad") → 0  (方片A)
     * - decodeFromStandard("Kd") → 12 (方片K)
     * - decodeFromStandard("Ah") → 26 (红桃A)
     * - decodeFromStandard("Ks") → 51 (黑桃K)
     */
    public static int decodeFromStandard(String card) {
        if (card == null || !CARD_PATTERN.matcher(card).matches()) {
            throw new IllegalArgumentException("Invalid card format: " + card + ". Expected format: [A2-9TJQK][dhcs]");
        }
        
        Integer code = CARD_TO_CODE.get(card);
        if (code == null) {
            throw new IllegalArgumentException("Unknown card: " + card);
        }
        
        return code;
    }
    
    /**
     * 批量转换：数字编码数组 → 标准格式数组
     * 
     * @param codes 数字编码数组
     * @return 标准格式字符串数组
     */
    public static String[] encodeToStandard(int[] codes) {
        if (codes == null) {
            return new String[0];
        }
        
        String[] cards = new String[codes.length];
        for (int i = 0; i < codes.length; i++) {
            cards[i] = encodeToStandard(codes[i]);
        }
        return cards;
    }
    
    /**
     * 批量转换：标准格式数组 → 数字编码数组
     * 
     * @param cards 标准格式字符串数组
     * @return 数字编码数组
     */
    public static int[] decodeFromStandard(String[] cards) {
        if (cards == null) {
            return new int[0];
        }
        
        int[] codes = new int[cards.length];
        for (int i = 0; i < cards.length; i++) {
            codes[i] = decodeFromStandard(cards[i]);
        }
        return codes;
    }
    
    /**
     * 验证牌面格式是否正确
     * 
     * @param card 牌面字符串
     * @return true表示格式正确
     */
    public static boolean isValidCard(String card) {
        if (card == null) {
            return false;
        }
        return CARD_PATTERN.matcher(card).matches() && CARD_TO_CODE.containsKey(card);
    }
    
    /**
     * 验证数字编码是否在有效范围内
     * 
     * @param code 数字编码
     * @return true表示有效
     */
    public static boolean isValidCode(int code) {
        return code >= 0 && code <= 51;
    }
    
    /**
     * 获取牌面的花色（中文）
     * 
     * @param card 标准格式或数字编码
     * @return 花色中文名称，如 "红桃", "方块"
     */
    public static String getSuitNameZh(String card) {
        int code = decodeFromStandard(card);
        return getSuitNameZh(code);
    }
    
    /**
     * 获取牌面的花色（中文）
     * 
     * @param code 数字编码
     * @return 花色中文名称
     */
    public static String getSuitNameZh(int code) {
        if (!isValidCode(code)) {
            throw new IllegalArgumentException("Invalid card code: " + code);
        }
        int suitIndex = code / 13;
        return SUIT_NAMES_ZH[suitIndex];
    }
    
    /**
     * 获取牌面的花色（英文）
     * 
     * @param card 标准格式或数字编码
     * @return 花色英文名称，如 "Hearts", "Diamonds"
     */
    public static String getSuitNameEn(String card) {
        int code = decodeFromStandard(card);
        return getSuitNameEn(code);
    }
    
    /**
     * 获取牌面的花色（英文）
     * 
     * @param code 数字编码
     * @return 花色英文名称
     */
    public static String getSuitNameEn(int code) {
        if (!isValidCode(code)) {
            throw new IllegalArgumentException("Invalid card code: " + code);
        }
        int suitIndex = code / 13;
        return SUIT_NAMES_EN[suitIndex];
    }
    
    /**
     * 获取牌面的点数名称
     * 
     * @param card 标准格式
     * @return 点数字符
     */
    public static char getRank(String card) {
        if (card == null || card.length() < 2) {
            throw new IllegalArgumentException("Invalid card: " + card);
        }
        return card.charAt(0);
    }
    
    /**
     * 获取牌面的花色字符
     * 
     * @param card 标准格式
     * @return 花色字符 (d/c/h/s)
     */
    public static char getSuit(String card) {
        if (card == null || card.length() < 2) {
            throw new IllegalArgumentException("Invalid card: " + card);
        }
        return card.charAt(1);
    }
    
    /**
     * 获取牌面的完整描述（中文）
     * 
     * @param card 标准格式或数字编码
     * @return 如 "红桃A", "方块K"
     */
    public static String getCardDescriptionZh(String card) {
        char rank = getRank(card);
        String suit = getSuitNameZh(card);
        String rankName = getRankNameZh(rank);
        return suit + rankName;
    }
    
    /**
     * 获取点数的中文名称
     * 
     * @param rank 点数字符
     * @return 中文名称
     */
    private static String getRankNameZh(char rank) {
        switch (rank) {
            case 'A': return "A";
            case 'T': return "10";
            case 'J': return "J";
            case 'Q': return "Q";
            case 'K': return "K";
            default: return String.valueOf(rank);
        }
    }
}

